package com.lanchetech.merchant.service.impl;


import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lanchetech.bean.request.MerchantRolePermissionReq;
import com.lanchetech.bean.request.PageReq;
import com.lanchetech.bean.request.SysLogReq;
import com.lanchetech.bean.request.UpdatePasswordReq;
import com.lanchetech.bean.response.BasePageResp;
import com.lanchetech.bean.response.BaseResp;
import com.lanchetech.bean.response.ResultData;
import com.lanchetech.bean.util.PageHelpUtil;
import com.lanchetech.bean.vo.MerchantDetailVO;
import com.lanchetech.common.enums.MsgUserRoleEnum;
import com.lanchetech.common.enums.ResultCode;
import com.lanchetech.dao.*;
import com.lanchetech.entity.*;
import com.lanchetech.merchant.config.JwtTokenUtil;
import com.lanchetech.merchant.service.MerchantService;
import com.lanchetech.service.DaoService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class MerchantServiceImpl implements MerchantService {

    @Autowired
    MerchantMapper merchantMapper;

    @Autowired
    UserMapper userMapper;

    @Autowired
    MerchantPermissionMapper merchantPermissionMapper;

    @Autowired
    MerchantRoleMapper merchantRoleMapper;

    @Autowired
    MerchantRolePermissionMapper merchantRolePermissionMapper;

    @Autowired
    SysLogMapper sysLogMapper;

    @Autowired
    DaoService daoService;

    @Autowired
    MsgUserMapper msgUserMapper;

    @Autowired
    JwtTokenUtil jwtTokenUtil;

    @Autowired
    TenantMapper tenantMapper;

    @Autowired
    ShopMapper shopMapper;

    @Autowired
    MerchantSysLogMapper merchantSysLogMapper;

    @Value("${im.jwt.secret}")
    public String secret;

    @Override
    public ResultData<MerchantDetailVO> getMerchantDetail(Merchant merchant) {
        MerchantDetailVO vo = new MerchantDetailVO();
        merchant.setPassword("");
        BeanUtils.copyProperties(merchant, vo);

        MsgUser msgUser = msgUserMapper.findOneByRelateIdAndRole(merchant.getId(), MsgUserRoleEnum.MERCHANT.getRole());
        Tenant tenant = tenantMapper.selectByPrimaryKey(merchant.getTenantId());
        Shop shop = shopMapper.selectByPrimaryKey(merchant.getTenantId());
        if(tenant != null){
            vo.setMsgAvatar(tenant.getAvatar());
        }
        if(shop != null){
            vo.setShopType(shop.getType());
            vo.setServiceRate(shop.getServiceRate());
        }
        if (msgUser != null) {
            vo.setChatToken(jwtTokenUtil.generateToken(msgUser, secret));
            vo.setMsgUserId(msgUser.getId());
            vo.setMsgNickname(msgUser.getNickname());
            vo.setMsgAvatar(msgUser.getAvatar());
            vo.setMsgServiceName(msgUser.getServiceName());
        }
        return new ResultData<>(vo);
    }

    @Override
    public ResultData<List<MerchantPermission>> getMerchantPermissions(Merchant merchant) {
        List<MerchantPermission> list = merchantPermissionMapper.getMerchantPermissionList(merchant.getRoleId());
        return new ResultData<>(list);
    }

    @Override
    public ResultData<BasePageResp<MerchantRole>> getMerchantRolePage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<MerchantRole> list = merchantRoleMapper.findAllPage(req);
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public BaseResp updatePassword(Merchant merchant, UpdatePasswordReq req) {
        // 验证老密码
        if (!new BCryptPasswordEncoder().matches(req.getOldPassword(), merchant.getPassword())) {
            return new BaseResp(ResultCode.PASSWORD_ERROR);
        }
        // 写入新密码
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        final String rawPassword = req.getNewPassword();

        Merchant updateMerchant = Merchant.builder()
                .id(merchant.getId())
                .password(encoder.encode(rawPassword))
                .lastPasswordResetDate(new Date())
                .updatedAt(new Date())
                .build();

        merchantMapper.updateByPrimaryKeySelective(updateMerchant);

        return new BaseResp();
    }

    @Override
    public BaseResp editMerchantRole(MerchantRole merchantRole) {
        if (merchantRole.getId() == null) {
            merchantRole.setName("ROLE_" + (merchantRoleMapper.findMaxId() + 1L));
            // 创建
            merchantRoleMapper.insert2(merchantRole);
            return new BaseResp();
        } else {
            // 修改
            merchantRole.setName(null);
            merchantRoleMapper.updateByPrimaryKeySelective(merchantRole);
            return new BaseResp();
        }
    }

    @Override
    public BaseResp deleteMerchantRole(Long id) {
        if (id.equals(1)) {
            return new BaseResp(ResultCode.FAIL);
        }
        merchantRolePermissionMapper.deleteByRoleId(id);
        merchantRoleMapper.deleteByPrimaryKey(id);
        return new BaseResp();
    }

    @Override
    public ResultData<List<MerchantPermission>> getMerchantRolePermissionList(Long id) {
        List<MerchantPermission> list = merchantRolePermissionMapper.getMerchantRolePermissionList(id);
        return new ResultData<>(list);
    }

    @Override
    public ResultData<List<MerchantPermission>> getAllPermissionList() {
        List<MerchantPermission> list = merchantPermissionMapper.findAll();
        return new ResultData<>(list);
    }

    @Override
    public BaseResp updateMerchantRolePermission(MerchantRolePermissionReq req) {
        merchantRolePermissionMapper.deleteByRoleId(req.getRoleId());
        merchantRolePermissionMapper.insertMerchantRolePermissions(req.getPermissions(), req.getRoleId());
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<Merchant>> getMerchantPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<Merchant> list = merchantMapper.findAllPage(req);
        Map<Long, MerchantRole> roleMap = daoService.getMerchantRoleMap(list.stream().map(Merchant::getRoleId).collect(Collectors.toList()));
        list.stream().forEach(item -> {
            item.setRegisterName(roleMap.get(item.getRoleId()).getDescription());
        });
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<List<MerchantRole>> getMerchantRoleList() {
        return new ResultData<>(merchantRoleMapper.findAll());
    }

    @Override
    public BaseResp editMerchant(Merchant merchant, Merchant req) {
        // 当前操作的管理员
        if (req.getId() == null) {
            // 判断账号是否已经存在
            Merchant result = merchantMapper.findOneByUsername(req.getUsername());
            if (result != null) {
                return new BaseResp(ResultCode.USER_EXISTED);
            }
            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
            final String rawPassword = req.getUsername();
            req.setPassword(encoder.encode(rawPassword))
                    .setAvatar("https://tccsmall.oss-cn-hangzhou.aliyuncs.com/resource/default-avatar2.png")
                    .setLastPasswordResetDate(new Date())
                    .setCreatedAt(new Date())
                    .setUpdatedAt(new Date())
                    .setStatus(1);
            merchantMapper.insert2(req);
        } else {
            req.setUpdatedAt(new Date());
            merchantMapper.updateByPrimaryKeySelective(req);
        }
        return new BaseResp();
    }

    @Override
    public BaseResp deleteMerchant(Merchant merchant, Long id) {
        merchantMapper.deleteByPrimaryKey(id);
        return new BaseResp();
    }

    @Override
    public BaseResp resetMerchantPassword(Long id) {
        if (id == 1) {
            return new BaseResp(ResultCode.FAIL);
        }
        Merchant merchant = merchantMapper.selectByPrimaryKey(id);
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        final String rawPassword = merchant.getUsername();
        Merchant updateMerchant = Merchant.builder()
                .id(id)
                .password(encoder.encode(rawPassword))
                .lastPasswordResetDate(new Date())
                .updatedAt(new Date())
                .build();

        merchantMapper.updateByPrimaryKeySelective(updateMerchant);

        return new BaseResp();
    }

    @Override
    public ResultData<Merchant> queryMerchantDetail(Long id) {
        return new ResultData<>(merchantMapper.selectByPrimaryKey(id));
    }

    @Override
    public ResultData<BasePageResp<MerchantSysLog>> getSysLogPage(SysLogReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<MerchantSysLog> list = merchantSysLogMapper.findAllPage(req);
        return PageHelpUtil.buildPage(list, page);
    }
}